﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using AMM.Model;
using AMM.Model.Project;

namespace AMM.DataAccess.Project {
    public class MouldRepository : BaseRepository<Mould> {

        private int _pageSize;

        public MouldRepository(int pageSize) {
            this._pageSize = pageSize;
        }

        public Mould FetchMouldById(int mouldId) {
            using (var ctx = this.Context) {
                return ctx.Moulds
                    .Include("MouldDetails")
                    .FirstOrDefault(x => x.MouldId == mouldId);
            }
        }

        public Mould FetchMouldByIdForView(int mouldId) {
            using (var ctx = this.Context) {
                return ctx.Moulds
                    .Include("MouldDetails")
                    .Include("MouldDetails.Material")
                    .Include("MouldDetails.Basic")
                    .FirstOrDefault(x => x.MouldId == mouldId);
            }
        }
        
        public void UpdateMould(Mould mould, Mould oldMould) {
            using (var ctx = this.Context) {
                using (DbContextTransaction trans = ctx.Database.BeginTransaction()) {
                    try {
                        mould.MouldDetails.Where(x => x.ClassStatus == ClassStatus.Added).ToList().ForEach(x => {
                            x.Mould = mould;
                            x.MouldId = mould.MouldId;
                            x.MouldDetailsId = Guid.NewGuid().GetHashCode();
                        });
                        // do not try to merge with above codes, because you can't change the fields which was marked as primary key
                        mould.MouldDetails.ToList().ForEach(x => {
                            ctx.MouldDetails.Attach(x);
                            switch (x.ClassStatus) {
                                case ClassStatus.UnChanged:
                                    ctx.MouldDetails.Attach(x);
                                    ctx.Entry(x).State = EntityState.Unchanged;
                                    break;
                                case ClassStatus.Updated:
                                    x.ModifiedBy = mould.ModifiedBy;
                                    x.ModifiedDatetime = DateTime.Now;
                                    ctx.MouldDetails.Attach(x);
                                    ctx.Entry(x).State = EntityState.Modified;
                                    break;
                                case ClassStatus.Added:
                                    x.CreatedBy = mould.ModifiedBy;
                                    x.CreatedDatetime = DateTime.Now;
                                    ctx.MouldDetails.Attach(x);
                                    ctx.Entry(x).State = EntityState.Added;
                                    break;
                                case ClassStatus.Deleted:
                                    ctx.MouldDetails.Attach(x);
                                    ctx.Entry(x).State = EntityState.Deleted;
                                    break;
                            }
                        });

                        ctx.Moulds.Attach(mould);
                        ctx.Entry(mould).State = EntityState.Modified;
                        ctx.SaveChanges();
                        trans.Commit();
                    }
                    catch (Exception ex) {
                        trans.Rollback();
                        throw ex;
                    }
                }
            }
        }

        public void DeleteMultipleMould(params int[] mouldIds) {
            using (var ctx = this.Context) {
                using (DbContextTransaction trans = ctx.Database.BeginTransaction()) {
                    try {
                        ctx.MouldDetails.Where(x => mouldIds.Contains(x.MouldId)).ToList().ForEach(x => {
                            ctx.MouldDetails.Remove(x);
                        });
                        ctx.Moulds.Where(x => mouldIds.Contains(x.MouldId)).ToList().ForEach(x => {
                            ctx.Moulds.Remove(x);
                        });
                        ctx.SaveChanges();
                        trans.Commit();
                    }
                    catch (Exception ex) {
                        trans.Rollback();
                        throw ex;
                    }
                }
            }
        }

        public List<Mould> FetchMouldList(MouldSearchModel searchModel, int pageIndex) {
            using (var ctx = this.Context) {
                var query = ctx.Moulds
                    .Include("Basic")
                    .Include("Vendor")
                    .Where(x => !string.IsNullOrEmpty(x.Code));

                if (!string.IsNullOrEmpty(searchModel.Code)) {
                    query = query.Where(x => x.Code.Contains(searchModel.Code));
                }
                if (!string.IsNullOrEmpty(searchModel.Name)) {
                    query = query.Where(x => x.Name.Contains(searchModel.Name));
                }
                if (!string.IsNullOrEmpty(searchModel.MouldFrameworkCode)) {
                    query = query.Where(x => x.MouldFrameworkCode.Contains(searchModel.MouldFrameworkCode));
                }
                if (searchModel.MouldTypeId.HasValue) {
                    query = query.Where(x => x.MouldType == searchModel.MouldTypeId.Value);
                }
                if (searchModel.VendorId.HasValue) {
                    query = query.Where(x => x.VendorId == searchModel.VendorId.Value);
                }

                searchModel.Records = query.Count();
                pageIndex = (pageIndex - 1) * this._pageSize > searchModel.Records ? 1 : pageIndex;

                return query.OrderByDescending(x => x.CreatedDatetime).Skip((pageIndex - 1) * this._pageSize).Take(this._pageSize).ToList();
            }
        }
    }
}
